package org.ihelpuoo.lang;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

/**
 * <b>TextUtil class:</b>
 * <hr color=grey size=1>
 *
 * All common methods for Text/String operation
 *
 * @author zozoh  created @ 2006
 *
 */
public class StringUtils
{
	/**
	 * Check a string is blank string or not.
	 * Whitespace will be ignore.
	 * 
	 * @param s
	 * @return string is blank or not
	 */
	public static boolean isBlank(CharSequence s)
	{
		if (null == s)
			return true;
		for (int i = 0; i < s.length(); i++)
		{
			if (!CharUtils.isWhiteSpace(s.charAt(i)))
				return false;
		}
		return true;
	}

	/**
	 * Check a string is empty string or not.
	 * 
	 * @param s
	 * @return string is empty or not
	 */
	public static boolean isEmpty(CharSequence s)
	{
		if (null == s)
			return true;
		return s.length() == 0;
	}

	/**
	 * It will generate the percentage Text
	 * 
	 * @param percent: a double value
	 * @return
	 */
	public static String parsePercentageText(double percent)
	{
		int intPercent = (int)percent;
		StringBuffer percentStr = new StringBuffer();
		if (intPercent == percent)
			percentStr.append(intPercent);
		else
			percentStr.append(percent);
		percentStr.append("%");
		return percentStr.toString();
	}

	/**
	 * @param s1
	 * @param s2
	 * @return
	 */
	public static boolean equalsIgnoreCase(String s1, String s2)
	{
		if (s1 == null || s2 == null)
			return false;
		return s1.equalsIgnoreCase(s2);
	}

	/**
	 * @param fn
	 * @return
	 */
	public static String getPackageNameFromClassFullName(String fn)
	{
		if (null == fn)
			return null;
		int pos = fn.lastIndexOf(".");
		if (pos < 0)
			return fn;
		return fn.substring(0,pos);
	}

	/**
	 * @param cs
	 * @param num
	 * @return
	 */
	public static CharSequence dup(CharSequence cs, int num)
	{
		if (cs == null || num <= 0)
			return "";
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < num; i++)
			sb.append(cs);
		return sb.toString();
	}

	public static CharSequence dup(char c, int num)
	{
		StringBuffer sb = new StringBuffer(c);
		for (int i = 1; i < num; i++)
			sb.append(c);
		return sb.toString();
	}

	public static int compare(CharSequence s1, CharSequence s2)
	{
		if (s1 == null && s2 == null)
			return 0;
		if (s1 == null)
			return -1;
		if (s2 == null)
			return 1;
		int len1 = s1.length();
		int len2 = s2.length();
		int max = Math.min(len1,len2);
		for (int i = 0; i < max; i++)
		{
			if (s1.charAt(i) < s2.charAt(i))
				return -1;
			if (s1.charAt(i) > s2.charAt(i))
				return 1;
		}
		if (len1 > len2)
			return 1;
		if (len1 < len2)
			return -1;
		return 0;
	}

	public static boolean equals(String s1, String s2)
	{
		return ObjectUtils.equals(s1,s2);
	}

	public static String capitalize(CharSequence s)
	{
		if (null == s)
			return null;
		if (s.length() == 0)
			return "";
		if (Character.isUpperCase(s.charAt(0)))
			return s.toString();
		StringBuffer sb = new StringBuffer();
		sb.append(Character.toUpperCase(s.charAt(0))).append(s.subSequence(1,s.length()));
		return sb.toString();
	}

	public static String firstLowercase(CharSequence s)
	{
		if (null == s)
			return null;
		if (s.length() == 0)
			return "";
		if (Character.isLowerCase(s.charAt(0)))
			return s.toString();
		StringBuffer sb = new StringBuffer();
		sb.append(Character.toLowerCase(s.charAt(0))).append(s.subSequence(1,s.length()));
		return sb.toString();
	}

	public static String lowercaseWordBy(CharSequence s, char ch)
	{
		if (null == s)
			return null;
		if (ch < 20)
			return s.toString();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < s.length(); i++)
		{
			char c = s.charAt(i);
			if (Character.isUpperCase(c))
			{
				if (i > 0)
					sb.append(ch);
				sb.append(Character.toLowerCase(c));
			}
			else
				sb.append(c);
		}
		return sb.toString();
	}

	public static String capitalizeWordBy(CharSequence s, char ch)
	{
		if (null == s)
			return null;
		if (ch < 20)
			return s.toString();
		StringBuffer sb = new StringBuffer();
		boolean up = false;
		for (int i = 0; i < s.length(); i++)
		{
			char c = s.charAt(i);
			if (c == ch)
			{
				up = true;
				continue;
			}
			sb.append(up ? Character.toUpperCase(c) : c);
			up = false;
		}
		return sb.toString();
	}

	public static boolean canBeClassName(CharSequence s)
	{
		if (null == s)
			return false;
		for (int i = 0; i < s.length(); i++)
		{
			if (CharUtils.isWordBoundery(s.charAt(i)))
				return false;
		}
		return false;
	}

	public static String trim(CharSequence s)
	{
		if (null == s)
			return null;
		if (s.length() == 0)
			return s.toString();
		if (s.length() == 1)
		{
			if (CharUtils.isWhiteSpace(s.charAt(0)))
				return "";
			return s.toString();
		}
		int start = 0;
		int lastIndex = s.length() - 1;
		int end = lastIndex;
		for (; start < s.length(); start++)
		{
			if (!CharUtils.isWhiteSpace(s.charAt(start)))
				break;
		}
		for (; end > 0; end--)
		{
			if (!CharUtils.isWhiteSpace(s.charAt(end)))
				break;
		}
		if (start > end)
			return "";
		else if (start == 0 && end == lastIndex)
			return s.toString();

		StringBuffer sb = new StringBuffer();
		for (int i = start; i <= end; i++)
			sb.append(s.charAt(i));

		return sb.toString();
	}

	public static String trimLeft(CharSequence s)
	{
		if (null == s)
			return null;
		if (s.length() == 0)
			return s.toString();
		if (s.length() == 1)
		{
			if (CharUtils.isWhiteSpace(s.charAt(0)))
				return "";
			return s.toString();
		}
		int start = 0;
		for (; start < s.length(); start++)
		{
			if (!CharUtils.isWhiteSpace(s.charAt(start)))
				break;
		}
		if (start == s.length())
			return "";
		else if (start == 0)
			return s.toString();

		int end = s.length() - 1;
		StringBuffer sb = new StringBuffer();
		for (int i = start; i <= end; i++)
			sb.append(s.charAt(i));

		return sb.toString();
	}

	public static String trimRight(CharSequence s)
	{
		if (null == s)
			return null;
		if (s.length() == 0)
			return s.toString();
		if (s.length() == 1)
		{
			if (CharUtils.isWhiteSpace(s.charAt(0)))
				return "";
			return s.toString();
		}
		int lastIndex = s.length() - 1;
		int end = lastIndex;
		for (; end > 0; end--)
		{
			if (!CharUtils.isWhiteSpace(s.charAt(end)))
				break;
		}
		if (end == 0)
			return "";
		else if (end == lastIndex)
			return s.toString();

		StringBuffer sb = new StringBuffer();
		for (int i = 0; i <= end; i++)
			sb.append(s.charAt(i));

		return sb.toString();
	}

	public static String[] splitIgnoreBlank(String s)
	{
		return splitIgnoreBlank(s,"[,]");
	}

	public static String[] splitIgnoreBlank(String s, String regex)
	{
		if (null == s)
			return null;
		String[] ss = s.split(regex);
		LinkedList<String> list = new LinkedList<String>();
		for (int i = 0; i < ss.length; i++)
		{
			if (StringUtils.isBlank(ss[i]))
				continue;
			list.add(trim(ss[i]));
		}
		String[] re = new String[list.size()];
		list.toArray(re);
		return re;
	}

	public static int len(String s)
	{
		if (null == s)
			return 0;
		return s.length();
	}

	public static CharSequence fillDigit(int d, int width)
	{
		return StringUtils.alignRight(String.valueOf(d),width,'0');
	}

	public static CharSequence fillHex(int d, int width)
	{
		return StringUtils.alignRight(Integer.toHexString(d),width,'0');
	}

	public static CharSequence alignRight(CharSequence cs, int width, char c)
	{
		if (null == cs)
			return null;
		if (cs.length() >= width)
			return cs;
		StringBuffer sb = new StringBuffer();
		int max = width - cs.length();
		for (int i = 0; i < max; i++)
			sb.append(c);
		sb.append(cs);
		return sb;
	}

	public static CharSequence alignLeft(CharSequence cs, int width, char c)
	{
		if (null == cs)
			return null;
		if (cs.length() >= width)
			return cs;
		StringBuffer sb = new StringBuffer();
		sb.append(cs);
		int max = width - cs.length();
		for (int i = 0; i < max; i++)
			sb.append(c);
		return sb;
	}

	public static boolean startsWith(CharSequence s, CharSequence sub)
	{
		if (null == s || sub == null)
			return false;
		if (s.length() < sub.length())
			return false;
		for (int i = 0; i < sub.length(); i++)
			if (s.charAt(i) != sub.charAt(i))
				return false;
		return true;
	}

	public static boolean endsWith(CharSequence s, CharSequence sub)
	{
		if (null == s || sub == null)
			return false;
		if (s.length() < sub.length())
			return false;
		int m = 0;
		int i = s.length() - sub.length();
		for (; i < s.length(); i++)
			if (s.charAt(i) != sub.charAt(m++))
				return false;
		return true;
	}

	private static Map<String, String>	words;

	public static String plural2singular(String word)
	{
		if (null == words)
			synchronized (StringUtils.class)
			{
				if (null == words)
				{
					words = new HashMap<String, String>();
					words.put("feet","foot");
					words.put("geese","goose");
					words.put("teeth","tooth");
					words.put("children","child");
					words.put("men","man");
					words.put("women","woman");
					words.put("mice","mouse");
					words.put("toys","toy");
					words.put("people","person");
					words.put("roofs","roof");
					words.put("proofs","proof");
					words.put("chiefs","chief");
					words.put("radios","radio");
					words.put("zoos","zoo");
					words.put("pianos","piano");
					words.put("photos","photo");
				}
			}
		String re = words.get(word);
		if (null == re)
		{
			if (word.endsWith("ses") || word.endsWith("xes") || word.endsWith("shes")
					|| word.endsWith("ches") || word.endsWith("oes"))
				re = word.substring(0,word.length() - 2);
			else if (word.endsWith("ies"))
				re = word.substring(0,word.length() - 3) + 'y';
			else if (word.endsWith("ves"))
				re = word.substring(0,word.length() - 3) + "fe";
			else if (word.endsWith("s"))
				re = word.substring(0,word.length() - 1);
			else
				re = word;
		}
		return re;
	}
}
